package com.google.code.stalkernet.server;

import java.net.SocketAddress;
import java.util.Collection;
import java.util.concurrent.CopyOnWriteArrayList;

import com.google.code.stalkernet.server.event.ServerEvent;
import com.google.code.stalkernet.server.event.ServerListener;

/**
 * Abstract base class for implementations of {@link Server} interface.
 *
 * @author Mikhail Vladimirov
 */
public abstract class AbstractServer implements Server
{
    private final Collection <ServerListener> serverListeners =
        new CopyOnWriteArrayList <> ();

    /**
     * {@inheritDoc}
     */
    @Override
    public void addServerListener (ServerListener serverListener)
    {
        if (serverListener == null)
            throw new IllegalArgumentException ("Server listener is null");

        serverListeners.add (serverListener);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void removeServerListener (ServerListener serverListener)
    {
        if (serverListener == null)
            throw new IllegalArgumentException ("Server listener is null");

        serverListeners.remove (serverListener);
    }

    /**
     * Get all registered server listeners.
     *
     * @return an array of {@link ServerListener} objects
     */
    public ServerListener [] getAllServerListeners ()
    {
        return serverListeners.toArray (
            new ServerListener [serverListeners.size ()]);
    }

    /**
     * Notify listeners about added socket address.
     *
     * @param socketAddress added socket address
     */
    protected void fireSocketAddressAdded (SocketAddress socketAddress)
    {
        if (socketAddress == null)
            throw new IllegalArgumentException ("Socket address is null");

        ServerEvent serverEvent = null;

        for (ServerListener serverListener: serverListeners)
        {
            if (serverEvent == null)
                serverEvent = new ServerEvent (this, socketAddress);

            serverListener.socketAddressAdded (serverEvent);
        }
    }

    /**
     * Notify listeners about remove socket address.
     *
     * @param socketAddress removed socket address
     */
    protected void fireSocketAddressRemoved (SocketAddress socketAddress)
    {
        if (socketAddress == null)
            throw new IllegalArgumentException ("Socket address is null");

        ServerEvent serverEvent = null;

        for (ServerListener serverListener: serverListeners)
        {
            if (serverEvent == null)
                serverEvent = new ServerEvent (this, socketAddress);

            serverListener.socketAddressRemoved (serverEvent);
        }
    }
}
